home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv2r1.tar / xv2r1 / extensions / xv / server / xvrop.c < prev   
C/C++ Source or Header  |  1991-09-25  |  44KB  |  1,889 lines

  1. /***********************************************************
  2. Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24. /*
  25. ** File: 
  26. **
  27. **   xvrop.c --- Xv RasterOps device dependent module.
  28. **
  29. ** Author: 
  30. **
  31. **   David Carver (Digital Workstation Engineering/Project Athena)
  32. **
  33. ** Revisions:
  34. **
  35. **   18.09.91 Carver
  36. **     - changed interface to libpip.c; now uses pip_src_area and pip_dst_area
  37. **       instead of pip_source_area, pip_origin, and pip_size.
  38. **     - fixed constrain procedure to clip video destination to screen bounds
  39. **
  40. **   10.09.91 Carver
  41. **     - fixed calls to fill_video_enable some were overrunning bounds
  42. **       of screen.
  43. **
  44. **   29.08.91 Carver
  45. **     - change: unrealizing windows no longer preempts video
  46. **     - added support for duty cycle (video priority) management
  47. **     - added support for video in StaticGray windows
  48. **     - added include of cfb.h; needed to access 8 plane gc priv structure
  49. **     - changed interfaces to rop.c and libpip.c to use RopPtr uniformly
  50. **     - changed ultrix conditional compile so this file works for both
  51. **       sun and dec boards
  52. **
  53. **   26.06.91 Carver
  54. **     - fixed GC wrapping logic in a big way
  55. **     - fixed XvropValidateGC; it had the wrong argument definition
  56. **       can't believe that it ever worked.
  57. **     - fixed XvropStopVideo to check to see if the GC still exists
  58. **       before it references a pointer to it.
  59. **
  60. **   11.06.91 Carver
  61. **     - changed SetPortControl to SetPortAttribute
  62. **     - changed GetPortControl to GetPortAttribute
  63. **     - changed QueryBestSize
  64. **
  65. **   04.06.91 Carver
  66. **     - completed implementing port controls
  67. **     - used code from R. Ulichney to to contrast and brightness calc's
  68. **     - changed interface to libpip.c, use new libpip.h header file
  69. **
  70. **   31.05.91 Carver
  71. **     - made big fixes to occlusion stuff
  72. **     - fixed video image offset and size
  73. **
  74. **   23.05.91 Carver
  75. **     - check for pip existance before initializing the adaptor
  76. **
  77. **   15.05.91 Carver
  78. **     - version 2.0 upgrade
  79. **
  80. **   24.04.91 Carver
  81. **     - updated to use 24 plane support.
  82. **
  83. **   19.03.91 Carver
  84. **     - origional version coded to v1r4.
  85. **
  86. */
  87.  
  88. #include <stdio.h>
  89.  
  90. #include <sys/types.h>
  91.  
  92. #include "X.h"
  93. #include "Xproto.h"
  94. #include "scrnintstr.h"
  95. #include "validate.h"
  96. #include "windowstr.h"
  97. #include "pixmapstr.h"
  98. #include "gcstruct.h"
  99. #include "dixstruct.h"
  100. #include "cfb.h"
  101.  
  102. #include "Xv.h"
  103. #include "Xvproto.h"
  104. #include "xvdix.h"
  105.  
  106. #ifdef ultrix
  107. #include <sys/workstation.h>        /* ULTRIX WORKSTATION DRIVER HEADER */
  108. #include <sys/pmagro.h>             /* ULTRIX RASTEROPS DRIVER HEADER */
  109. #endif ultrix
  110.  
  111. #ifdef DECWINDOWS
  112. #include "tfb.h"
  113. #else
  114. #define tfbPrivGCPtr cfbPrivGCPtr
  115. #define tfbGCPrivateIndex cfbGCPrivateIndex
  116. #endif
  117.  
  118. #define GLOBAL
  119. #include "xvrop.h"
  120. #undef GLOBAL
  121.  
  122. /* INTERNAL */
  123.  
  124. static Bool XvropCloseScreen();
  125. static int XvropQueryAdaptors();
  126. static int XvropInitAdaptor();
  127. static int XvropAllocatePort();
  128. static int XvropFreePort();
  129. static int XvropPutVideo();
  130. static int XvropPutStill();
  131. static int XvropGetVideo();
  132. static int XvropGetStill();
  133. static int XvropStopVideo();
  134. static int XvropSetPortAttribute();
  135. static int XvropGetPortAttribute();
  136. static int XvropQueryBestSize();
  137.  
  138. static pointer XvropPipInit();
  139.  
  140. static void XvropClipNotify();
  141. static void XvropCopyWindow();
  142. static Bool XvropUnrealizeWindow();
  143. static void XvropWindowExposures();
  144.  
  145. static void XvropDestroyGC();
  146. static void XvropValidateGC();
  147.  
  148. /* NOTE THAT WE ONLY NEED TO WRAP ONE GC AT A TIME; FOR THIS REASON WE DON'T
  149.    USE A GC PRIVATE STRUCTURE TO SAVE THE WRAP FUNCS; WHEN WE ARE FINISHED
  150.    USING A GC FOR VIDEO WE WANT TO UNWRAP IT, BUT WE NEED TO BE IN A FUNC IN 
  151.    ORDER TO UNWRAP IT, SO WE USE ChangeGC WITH A NULL MASK TO DO THE
  152.    UNWRAPPING; ITS A HACK BUT SAVES UNNECESSARY ALLOCATIONS */
  153.  
  154. static void XvropValidateGC (),  XvropCopyGC (),      XvropDestroyGC();
  155. static void XvropChangeGC();
  156. static void XvropChangeClip(),   XvropDestroyClip(),  XvropCopyClip();
  157.  
  158. static GCFuncs  XvropGCFuncs = 
  159. {
  160.   XvropValidateGC,
  161.   XvropChangeGC,
  162.   XvropCopyGC,
  163.   XvropDestroyGC,
  164.   XvropChangeClip,
  165.   XvropDestroyClip,
  166.   XvropCopyClip
  167. };
  168.  
  169. int
  170. XvropScreenInit(pScreen)
  171.  
  172. ScreenPtr pScreen;
  173.  
  174. {
  175.   XvropScreenPtr props;
  176.   XvScreenPtr pxvs;
  177.   int status;
  178.  
  179.   /* ALL XV DD SCREEN INIT PROCS NEED TO CALL THE DI SCREEN INIT PROC FIRST */
  180.  
  181.   XvScreenInit(pScreen);
  182.  
  183.   pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
  184.  
  185.   if ((status = XvropInitAdaptor(pScreen)) != Success)
  186.     return status;
  187.  
  188.  
  189.   /* XXX --- THESE SHOULD BE CHAINED FOR MULTIPLE ADAPTOR SUPPORT */
  190.  
  191.   pxvs->ddCloseScreen = XvropCloseScreen;
  192.   pxvs->ddQueryAdaptors = XvropQueryAdaptors;
  193.  
  194.   if (!(props = (XvropScreenPtr)xalloc(sizeof(XvropPortRec))))
  195.     {
  196.       return BadAlloc;
  197.     }
  198.   pxvs->devPriv.ptr = (pointer)props;
  199.  
  200.   props->WindowExposures = pScreen->WindowExposures;
  201.   pScreen->WindowExposures = XvropWindowExposures;
  202.  
  203.   props->UnrealizeWindow = pScreen->UnrealizeWindow;
  204.   pScreen->UnrealizeWindow = XvropUnrealizeWindow;
  205.  
  206.   props->CopyWindow = pScreen->CopyWindow;
  207.   pScreen->CopyWindow = XvropCopyWindow;
  208.  
  209.   props->ClipNotify = pScreen->ClipNotify;
  210.   pScreen->ClipNotify = XvropClipNotify;
  211.  
  212.   return Success;
  213. }
  214.  
  215. static int
  216. XvropInitAdaptor(pScreen)
  217.  
  218. ScreenPtr pScreen;
  219.  
  220. {
  221.   int id,status,count,np,ne,nd,nv,nf,tf,na,nvis;
  222.   XvScreenPtr pxvs;
  223.   XvAdaptorPtr pa,pas;
  224.   XvPortPtr pp,pps;
  225.   XvropPortPtr ppp;
  226.   XvEncodingPtr pe,pes;
  227.   XvFormatPtr pf,pfs;
  228.   unsigned long *pv;
  229.   VisualPtr pvis;
  230.   DepthPtr pd;
  231.   pointer prop;
  232.  
  233.   if (!(prop = XvropPipInit(pScreen)))
  234.     return Success;
  235.  
  236.   pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr;
  237.  
  238.   pas = (XvAdaptorPtr)xalloc(sizeof(XvAdaptorRec));
  239.   if (!pas)
  240.     {
  241.       FatalError("XvropInitAdaptors: coudn't alloc Adaptor struct\n");
  242.     }
  243.   pa = pas;
  244.  
  245.   for (na = 0; na<XVROP_NUM_ADAPTORS; na++)
  246.     {
  247.  
  248.       pes = (XvEncodingPtr)xalloc(sizeof(XvEncodingRec)*XvropNumEncodings[na]);
  249.       if (!pes)
  250.     {
  251.       FatalError("XvropInitAdaptors: coudn't alloc Encoding struct\n");
  252.     }
  253.  
  254.       pe = pes;
  255.  
  256.       for (ne = 0; ne<XvropNumEncodings[na]; ne++)
  257.     {
  258.       *pe = XvropEncodings[na][ne];
  259.       pe->pScreen = pScreen;
  260.       
  261.       pe++;
  262.     }
  263.  
  264.       pps = (XvPortPtr)xalloc(sizeof(XvPortRec)*XvropNumPorts[na]);
  265.       if (!pps)
  266.     {
  267.       FatalError("XvropInitAdaptors: coudn't alloc Port struct\n");
  268.     }
  269.       pp = pps;
  270.  
  271.       for (np = 0; np<XvropNumPorts[na]; np++)
  272.     {
  273.       id = FakeClientID(0);
  274.       
  275.       if (!AddResource(id, XvRTPort, pp))
  276.         {
  277.           FatalError("XvddInitScreen: couldn't add Port resource\n");
  278.         }
  279.       
  280.       /* MANUALLY FILL IN PORT STRUCTURE */
  281.       
  282.       pp->id = id;
  283.       pp->pAdaptor = pa;
  284.       pp->pDraw = (DrawablePtr)NULL;
  285.       pp->grab.client = (ClientPtr)NULL;
  286.       pp->time = currentTime;
  287.       pp->pNotify = (XvPortNotifyPtr)NULL;
  288.       ppp = (XvropPortPtr)xalloc(sizeof(XvropPortRec));
  289.       pp->devPriv.ptr = (pointer)ppp;
  290.  
  291.       ppp->pGC = (GCPtr)NULL;
  292.       ppp->pEncoding = pes; /* XXX---SHOULD BE A COMMAND LINE ARG */
  293.       ppp->hue = 0;
  294.       ppp->saturation = 0;
  295.       ppp->brightness = 0;
  296.       ppp->contrast = 0;
  297.       ppp->serialNumber = 0;
  298.  
  299.       /* SAVE HANDLE TO DEVICE DRIVER */
  300.  
  301.       ppp->prop = prop; 
  302.  
  303.       /* SET DEFAULT ENCODING; NOT GRAY */
  304.  
  305.       ppp->gray = FALSE;
  306.  
  307.       pip_source_type(ppp->prop, ppp->pEncoding->id);
  308.  
  309.       pp++;
  310.       
  311.     }
  312.  
  313.       nf = 0;
  314.       tf = XvropNumFormats[na];
  315.       pfs = (XvFormatPtr)xalloc(sizeof(XvFormatRec)*tf);
  316.       if (!pfs)
  317.     {
  318.       FatalError("XvropInitAdaptors: couldn't alloc Format struct\n");
  319.     }
  320.       pf = pfs;
  321.  
  322.       pd = pScreen->allowedDepths;
  323.       for (nd=0; nd<pScreen->numDepths; nd++)
  324.     {
  325.       if (pd->depth == 24)
  326.         {
  327.           pv = pd->vids;
  328.           for (nv=0; nv<pd->numVids; nv++)
  329.         {
  330.           if (nf >= tf) 
  331.             {
  332.               tf *= 2;
  333.               pfs = (XvFormatPtr)xrealloc(pfs, sizeof(XvFormatRec)*tf);
  334.               pf = &pfs[nf];
  335.             }
  336.           
  337.           pf->depth = pd->depth;
  338.           pf->visual = *pv;
  339.           pf++;
  340.           nf++;
  341.           pv++;
  342.         }
  343.         }
  344.       pd++;
  345.     }
  346.  
  347.       /* FIND STATIC GRAY VISUAL */
  348.  
  349.       pvis = pScreen->visuals;
  350.       for (nvis=0; nvis<pScreen->numVisuals; nvis++)
  351.     {
  352.       if (pvis->class == StaticGray) break;
  353.       pvis++;
  354.     }
  355.  
  356.       /* IF WE FOUND ONE THEN FIND MATCHING DEPTH VISUALID */
  357.  
  358.       if (nvis < pScreen->numVisuals)
  359.     {
  360.       pd = pScreen->allowedDepths;
  361.       for (nd=0; nd<pScreen->numDepths; nd++)
  362.         {
  363.           if (pd->depth == 8)
  364.         {
  365.           pv = pd->vids;
  366.           for (nv=0; nv<pd->numVids; nv++)
  367.             {
  368.               if (pvis->vid == *pv)
  369.             {
  370.               if (nf >= tf) 
  371.                 {
  372.                   tf *= 2;
  373.                   pfs = (XvFormatPtr)
  374.                 xrealloc(pfs, sizeof(XvFormatRec)*tf);
  375.                   pf = &pfs[nf];
  376.                 }
  377.               pf->depth = pd->depth;
  378.               pf->visual = *pv;
  379.               pf++;
  380.               nf++;
  381.               break;
  382.             }
  383.               pv++;
  384.             }
  385.         }
  386.           pd++;
  387.         }
  388.     }
  389.       XvropNumFormats[na] = nf;
  390.  
  391.       pp = pps+na;
  392.       pa->base_id = pp->id;
  393.       pa->type = XvInputMask;
  394.       pa->name = "RasterOps";
  395.       pa->nEncodings = ne;
  396.       pa->pEncodings = pes;
  397.       pa->nPorts = np;
  398.       pa->pPorts = pps;
  399.       pa->nFormats = nf;
  400.       pa->pFormats = pfs;
  401.       pa->pScreen = pScreen;
  402.       pa->ddAllocatePort = XvropAllocatePort;
  403.       pa->ddFreePort = XvropFreePort;
  404.       pa->ddPutVideo = XvropPutVideo;
  405.       pa->ddPutStill = XvropPutStill;
  406.       pa->ddGetVideo = XvropGetVideo;
  407.       pa->ddGetStill = XvropGetStill;
  408.       pa->ddStopVideo = XvropStopVideo;
  409.       pa->ddSetPortAttribute = XvropSetPortAttribute;
  410.       pa->ddGetPortAttribute = XvropGetPortAttribute;
  411.       pa->ddQueryBestSize = XvropQueryBestSize;
  412.  
  413.       /* ALLOWS QUICK ACCESS TO PORTS BY ROP DD MODULE */
  414.  
  415.       XvropPorts = pps;
  416.     }
  417.  
  418.   pxvs->nAdaptors = na;
  419.   pxvs->pAdaptors = pas;
  420.  
  421.   /* ALLOCATE ATOMS FOR PORT ATTRIBUTES --- MORE LATER */
  422.  
  423.   XvropEncoding = MakeAtom("XV_ENCODING", strlen("XV_ENCODING"), xTrue);
  424.   XvropHue = MakeAtom("XV_HUE", strlen("XV_HUE"), xTrue);
  425.   XvropSaturation = MakeAtom("XV_SATURATION", strlen("XV_SATURATION"), xTrue);
  426.   XvropBrightness = MakeAtom("XV_BRIGHTNESS", strlen("XV_BRIGHTNESS"), xTrue);
  427.   XvropContrast = MakeAtom("XV_CONTRAST", strlen("XV_CONTRAST"), xTrue);
  428.  
  429.   return Success;
  430.  
  431. }
  432.  
  433. static pointer
  434. XvropPipInit(pScreen)
  435. ScreenPtr pScreen;
  436.  
  437. {
  438.   pointer prop;
  439.  
  440.   /* XXX---INIT TO USE NTSC; THIS SHOULD BE SERVER OPTION */
  441.  
  442.   if (!(prop = (pointer)pip_init(pScreen->myNum, PIP_NTSC | PIP_COMPOSITE)))
  443.     return prop;
  444.  
  445.   fill_video_enable(prop, 0, 0, pScreen->width, pScreen->height, 00);
  446.  
  447.   return prop;
  448.  
  449. }
  450.  
  451. static Bool
  452. XvropCloseScreen(ii, pScreen)
  453. int ii;
  454. ScreenPtr pScreen;
  455.  
  456. {
  457.   int np,na;
  458.   XvAdaptorPtr pa;
  459.   XvPortPtr pp;
  460.   XvScreenPtr pxvs;
  461.   XvropScreenPtr props;
  462.  
  463.   pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr;
  464.   props = (XvropScreenPtr)pxvs->devPriv.ptr;
  465.  
  466.   if (!pxvs) return TRUE;
  467.  
  468.   pScreen->WindowExposures = props->WindowExposures;
  469.  
  470.   pScreen->UnrealizeWindow = props->UnrealizeWindow;
  471.  
  472.   pScreen->CopyWindow = props->CopyWindow;
  473.   pScreen->ClipNotify = props->ClipNotify;
  474.  
  475.   pa = pxvs->pAdaptors;
  476.  
  477.   for (na=0; na<pxvs->nAdaptors; na++, pa++)
  478.     {
  479.       if (pa->pFormats) xfree(pa->pFormats);
  480.       if (pa->pEncodings) xfree(pa->pEncodings);
  481.       pp = pa->pPorts;
  482.       for (np=0; np<pa->nPorts; np++, pp++)
  483.     {
  484.       if (pp->devPriv.ptr) xfree(pp->devPriv.ptr);
  485.     }
  486.       if (pa->pPorts) xfree(pa->pPorts);
  487.     }
  488.  
  489.   xfree(pxvs->pAdaptors);
  490.   pxvs->pAdaptors = (XvAdaptorPtr)NULL;
  491.  
  492.   return TRUE;
  493. }
  494.  
  495. static int
  496. XvropAllocatePort(port, pPort, ppPort)
  497.  
  498. unsigned long port;
  499. XvPortPtr pPort;
  500. XvPortPtr *ppPort;
  501.  
  502. {
  503.   *ppPort = pPort;
  504.   return Success;
  505. }
  506.  
  507. static int
  508. XvropFreePort(pPort)
  509.  
  510. XvPortPtr pPort;
  511.  
  512. {
  513.   return Success;
  514. }
  515.  
  516. static int
  517. XvropQueryAdaptors(pScreen, p_nAdaptors, p_pAdaptors)
  518.  
  519. ScreenPtr pScreen;
  520. XvAdaptorPtr *p_pAdaptors;
  521. int *p_nAdaptors;
  522.  
  523. {
  524.  
  525.   XvScreenPtr pxvs;
  526.  
  527.   pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr;
  528.  
  529.   *p_nAdaptors = pxvs->nAdaptors;
  530.   *p_pAdaptors = pxvs->pAdaptors;
  531.  
  532.   return (Success);
  533.  
  534. }
  535.  
  536. static void
  537. XvropConstrainVideo(pWin, pe,
  538.             vid_x, vid_y, vid_w, vid_h,
  539.             drw_x, drw_y, drw_w, drw_h,
  540.             p_vid_x, p_vid_y, p_vid_w, p_vid_h,
  541.             p_drw_x, p_drw_y, p_drw_w, p_drw_h)
  542.  
  543. WindowPtr pWin;
  544. XvEncodingPtr pe;
  545. INT16 vid_x, vid_y, drw_x, drw_y;
  546. INT16 vid_w, vid_h, drw_w, drw_h;
  547. INT16 *p_vid_x, *p_vid_y, *p_drw_x, *p_drw_y;
  548. INT16 *p_vid_w, *p_vid_h, *p_drw_w, *p_drw_h;
  549.  
  550. {
  551.   ScreenPtr pScreen;
  552.   int u,v;
  553.  
  554.   /* NOTE WE ARE USING SIGNED VALUES FOR EXTENTS; THE CALCULATIONS BELOW COULD
  555.      PRODUCE NEGATIVE VALUES WHICH SHOULD BE INTERPRETED AS A NULL VIDEO
  556.      REGION */
  557.  
  558.   /* INITIALIZE RESULTS TO ZERO IN CASE WE ENCOUNTER A ZERO EXTENT SOMEWHERE
  559.      ALONG THE WAY */
  560.  
  561.   /* USE A LOOP TO HANDLE SIZE ERROR */
  562.  
  563.   while (1)
  564.     {
  565.       
  566.       /* FIRST SEE IF VID X,Y ARE OUT OF BOUNDS; NULL REGION RESULTS */
  567.       
  568.       if (vid_x >= pe->width || vid_y >= pe->height || 
  569.       vid_w <= 0 || vid_h <= 0) break;
  570.       
  571.       /* CLIP LOWER BOUNDS OF SOURCE REGION */
  572.       
  573.       if (vid_x < 0)
  574.     {
  575.       u = (drw_w*(vid_w + vid_x))/vid_w;
  576.       drw_x += drw_w - u;
  577.       drw_w = u;
  578.       vid_w += vid_x;
  579.       vid_x = 0;
  580.       if (drw_w <= 0 || vid_w <= 0) break;
  581.     }
  582.       
  583.       if (vid_y < 0)
  584.     {
  585.       u = (drw_h*(vid_h + vid_y))/vid_h;
  586.       drw_y += drw_h - u;
  587.       drw_h = u;
  588.       vid_h += vid_y;
  589.       vid_y = 0;
  590.       if (drw_h <= 0 || vid_h <= 0) break;
  591.     }
  592.       
  593.       /* CLIP UPPER BOUNDS OF SOURCE REGION */
  594.       
  595.       if (vid_x + vid_w > pe->width)
  596.     {
  597.       drw_w = (drw_w*(pe->width - vid_x))/vid_w;
  598.       vid_w = pe->width - vid_x;
  599.       if (drw_w <= 0 || vid_w <= 0) break;
  600.     }
  601.       
  602.       if (vid_y + vid_h > pe->height)
  603.     {
  604.       drw_h = (drw_h*(pe->height - vid_y))/vid_h;
  605.       vid_h = pe->height - vid_y;
  606.       if (drw_h <= 0 || vid_h <= 0) break;
  607.     }
  608.       
  609.       /* CLIP THE DST AREA TO THE LOWER BOUNDS OF SCREEN */
  610.       
  611.       if (pWin->drawable.x + drw_x < 0)
  612.     {
  613.       u = drw_w + (pWin->drawable.x + drw_x);
  614.       v = (vid_w*u)/drw_w;
  615.       vid_x += vid_w - v;
  616.       vid_w = v;
  617.       drw_x = -pWin->drawable.x;
  618.       drw_w = u;
  619.       if (drw_w <= 0 || vid_w <= 0) break;
  620.     }
  621.       
  622.       if (pWin->drawable.y + drw_y < 0)
  623.     {
  624.       if (drw_h <= 0) break;
  625.       u = drw_h + (pWin->drawable.y + drw_y);
  626.       v = (vid_h*u)/drw_h;
  627.       vid_y += vid_h - v;
  628.       vid_h = v;
  629.       drw_y = -pWin->drawable.y;
  630.       drw_h = u;
  631.       if (drw_h <= 0 || vid_h <= 0) break;
  632.     }
  633.       
  634.       /* CLIP THE DST AREA TO THE UPPER BOUNDS OF SCREEN */
  635.       
  636.       pScreen = pWin->drawable.pScreen;
  637.       
  638.       if (pWin->drawable.x + drw_x + drw_w > pScreen->width)
  639.     {
  640.       u = pScreen->width - pWin->drawable.x - drw_x;
  641.       vid_w = (vid_w*u)/drw_w;
  642.       drw_w = u;
  643.       if (drw_w <= 0 || vid_w <= 0) break;
  644.     }
  645.       
  646.       if (pWin->drawable.y + drw_y + drw_h > pScreen->height)
  647.     {
  648.       u = pScreen->height - pWin->drawable.y - drw_y;
  649.       vid_h = (vid_h*u)/drw_h;
  650.       drw_h = u;
  651.       if (drw_h <= 0 || vid_h <= 0) break;
  652.     }
  653.       
  654.       /* CHECK DESTINATION SIZE AGAINST SOURCE VIDEO SIZE */
  655.       
  656.       if (drw_w > vid_w)
  657.     {
  658.       drw_h = (drw_h * vid_w)/drw_w;
  659.       drw_w = vid_w;
  660.       if (drw_w <= 0 || vid_w <= 0) break;
  661.     }
  662.       
  663.       if (drw_h > vid_h)
  664.     {
  665.       drw_w = (drw_w * vid_h)/drw_h;
  666.       drw_h = vid_h;
  667.       if (drw_h <= 0 || vid_h <= 0) break;
  668.     }
  669.       
  670.       *p_vid_x = vid_x;
  671.       *p_vid_y = vid_y;
  672.       *p_vid_w = vid_w;
  673.       *p_vid_h = vid_h;
  674.       *p_drw_x = drw_x;
  675.       *p_drw_y = drw_y;
  676.       *p_drw_w = drw_w;
  677.       *p_drw_h = drw_h;
  678.  
  679.       return;
  680.  
  681.     }
  682.  
  683.   *p_vid_x = 0;
  684.   *p_vid_y = 0;
  685.   *p_vid_w = 0;
  686.   *p_vid_h = 0;
  687.   *p_drw_x = 0;
  688.   *p_drw_y = 0;
  689.   *p_drw_w = 0;
  690.   *p_drw_h = 0;
  691.  
  692. }
  693.  
  694. static int
  695. XvropPutVideo(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  696.            drw_x, drw_y, drw_w, drw_h)
  697.  
  698. ClientPtr client;
  699. DrawablePtr pDraw;
  700. XvPortPtr pPort;
  701. GCPtr pGC;
  702. INT16 vid_x, vid_y, drw_x, drw_y;
  703. CARD16 vid_w, vid_h, drw_w, drw_h;
  704.  
  705. {
  706.   XvropPortPtr ppp;
  707.   cfbPrivGCPtr pCFBGC;
  708.   tfbPrivGCPtr pTFBGC;
  709.   GCPtr pGCTemp;
  710.   int vis,nBox,x1,x2,y1,y2;
  711.   int lx,ly,hx,hy;
  712.   BoxPtr pBox;
  713.   RegionPtr pClip;
  714.  
  715.   if (pDraw->type != DRAWABLE_WINDOW)
  716.     {
  717.       pPort->pDraw = (DrawablePtr)NULL;
  718.       return BadAlloc;
  719.     }
  720.  
  721.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  722.  
  723.   /* SAVE PARAMETERS */
  724.  
  725.   ppp->vx = vid_x;
  726.   ppp->vy = vid_y;
  727.   ppp->vw = vid_w;
  728.   ppp->vh = vid_h;
  729.   ppp->dx = drw_x;
  730.   ppp->dy = drw_y;
  731.   ppp->dw = drw_w;
  732.   ppp->dh = drw_h;
  733.  
  734.   /* CONSTRAIN THE REGIONS TO THOSE THAT ARE SUPPORTED; MAINTAIN ASPECT
  735.      RATIO WHEN POSSIBLE */
  736.  
  737.   XvropConstrainVideo(pDraw, ppp->pEncoding, 
  738.               vid_x, vid_y, vid_w, vid_h,
  739.               drw_x, drw_y, drw_w, drw_h,
  740.               &vid_x, &vid_y, &vid_w, &vid_h,
  741.               &drw_x, &drw_y, &drw_w, &drw_h);
  742.  
  743.   /* UNWRAP THE OLD GC PROCEDURES IF NECESSARY */
  744.  
  745.   if ((ppp->pGC) && (pGC != ppp->pGC))
  746.     {
  747.       pGCTemp = ppp->pGC;
  748.       ppp->pGC = (GCPtr)NULL;
  749.       ChangeGC(pGCTemp, 0, 0); /* USE CHANGE GC TO UNWRAP GC */
  750.     }
  751.  
  752.   /* TURN PIP OFF SO WE CAN CHANGE PARAMETERS */
  753.  
  754.   pip_off_with_timeout(ppp->prop, 1);
  755.  
  756.   /* IF THE DRAWABLE DEPTH IS 8 WE KNOW IT MUST BE A StaticGray WINDOW */
  757.  
  758.   if (pDraw->depth == 8)
  759.     {
  760.       if (!ppp->gray)
  761.     {
  762.       pip_source_type(ppp->prop, ppp->pEncoding->id | PIP_GRAY);
  763.       ppp->gray = TRUE;
  764.     }
  765.  
  766.       /* GET COMPOSITE CLIP LIST */
  767.  
  768.       pCFBGC = (cfbPrivGCPtr)pGC->devPrivates[cfbGCPrivateIndex].ptr; 
  769.       pClip = pCFBGC->pCompositeClip;
  770.  
  771.     }
  772.   else
  773.     {
  774.       if (ppp->gray)
  775.     {
  776.       pip_source_type(ppp->prop, ppp->pEncoding->id);
  777.       ppp->gray = FALSE;
  778.     }
  779.  
  780.       /* GET COMPOSITE CLIP LIST */
  781.  
  782.       pTFBGC = (tfbPrivGCPtr)pGC->devPrivates[tfbGCPrivateIndex].ptr; 
  783.       pClip = pTFBGC->pCompositeClip;
  784.  
  785.     }
  786.  
  787.   /* THIS IS A LITTLE UNCLEAR; BUT WE WANT TO UPDATE THE VIDEO MASK
  788.      IF EITHER THE DRAWABLE OR GC HAS CHANGED; WE TRAP GC VALIDATES
  789.      AND CHANGE THE PORT SERIAL NUMBER SO THAT WE KNOW IF THE GC
  790.      HAS CHANGED */
  791.  
  792.   if ((pGC != ppp->pGC) || (pDraw->serialNumber != ppp->serialNumber))
  793.     {
  794.  
  795.       ppp->serialNumber = pDraw->serialNumber;
  796.  
  797.       if (pPort->pDraw)
  798.     {
  799.  
  800.       /* CLEAR THE OLD VIDEO ENABLED REGION */
  801.  
  802.       fill_video_enable(ppp->prop, 
  803.                 ppp->enabled_box.x1, 
  804.                 ppp->enabled_box.y1, 
  805.                 ppp->enabled_box.x2 - ppp->enabled_box.x1,
  806.                 ppp->enabled_box.y2 - ppp->enabled_box.y1, 00);
  807.     }
  808.  
  809.       for (nBox=0, pBox=REGION_RECTS(pClip);
  810.        nBox<(int)REGION_NUM_RECTS(pClip); 
  811.        nBox++, pBox++)
  812.     {
  813.       
  814.       x1 = pBox->x1;
  815.       y1 = pBox->y1;
  816.       x2 = pBox->x2;
  817.       y2 = pBox->y2;
  818.       
  819.       fill_video_enable(ppp->prop, x1, y1, x2 - x1, y2 - y1, 0xff);
  820.       
  821.     }
  822.  
  823.       /* SAVE THE BOUNDING BOX OF THE ENABLED VIDEO REGION */
  824.  
  825.       ppp->enabled_box = pClip->extents;
  826.  
  827.     }
  828.  
  829.   vis = ((WindowPtr)pDraw)->visibility;
  830.  
  831.   if (vis == VisibilityUnobscured) pip_priority(ppp->prop, 0);
  832.   else pip_priority(ppp->prop, 256);
  833.  
  834.   pip_src_area(ppp->prop, vid_x, vid_y, vid_w, vid_h);
  835.  
  836.   pip_dst_area(ppp->prop, pDraw->x+drw_x, pDraw->y+drw_y, drw_w, drw_h);
  837.  
  838.   /* TURN PIP ON IF IT WASN'T LEFT ON */
  839.  
  840.   if (!pip_on_with_timeout(ppp->prop, 1))
  841.     {
  842.       XvdiSendVideoNotify(pPort, pDraw, XvHardError);
  843.       
  844.       /* UNWRAP GC IF NECESSARY */
  845.       
  846.       if (pGC == ppp->pGC)
  847.     {
  848.       ppp->pGC = (GCPtr)NULL;
  849.       ChangeGC(pGC, 0, 0); /* USE CHANGE GC TO UNWRAP GC */
  850.     }
  851.  
  852.       ppp->pGC = (GCPtr)NULL;
  853.       pPort->pDraw = (DrawablePtr)NULL;
  854.       
  855.       return Success;
  856.     }
  857.  
  858.   /* WRAP THE NEW GC PROCEDURES IF NECESSARY */
  859.  
  860.   if (pGC != ppp->pGC)
  861.     {
  862.       ppp->pGC = pGC;
  863.       ppp->wrapFuncs = pGC->funcs;
  864.       pGC->funcs = &XvropGCFuncs;
  865.     }
  866.  
  867.   pPort->pDraw = pDraw;
  868.  
  869.   return Success;
  870. }
  871.  
  872. static int
  873. XvropPutStill(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  874.            drw_x, drw_y, drw_w, drw_h)
  875. ClientPtr client;
  876. DrawablePtr pDraw;
  877. XvPortPtr pPort;
  878. GCPtr pGC;
  879. INT16 vid_x, vid_y, drw_x, drw_y;
  880. CARD16 vid_w, vid_h, drw_w, drw_h;
  881.  
  882. {
  883.   XvropPortPtr ppp;
  884.   XvEncodingPtr pe;
  885.   tfbPrivGCPtr pTFBGC;
  886.   cfbPrivGCPtr pCFBGC;
  887.   int vis,nBox,x1,x2,y1,y2;
  888.   int lx,ly,hx,hy;
  889.   BoxPtr pBox;
  890.   RegionPtr pClip;
  891.  
  892.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  893.  
  894.   if (pDraw->type != DRAWABLE_WINDOW)
  895.     {
  896.       return BadAlloc;
  897.     }
  898.  
  899.   /* CONSTRAIN THE REGIONS TO THOSE THAT ARE SUPPORTED */
  900.  
  901.   pe = ppp->pEncoding;
  902.  
  903.   XvropConstrainVideo(pDraw, pe, 
  904.               vid_x, vid_y, vid_w, vid_h,
  905.               drw_x, drw_y, drw_w, drw_h,
  906.               &vid_x, &vid_y, &vid_w, &vid_h,
  907.               &drw_x, &drw_y, &drw_w, &drw_h);
  908.  
  909.   /* GET COMPOSITE CLIP LIST */
  910.  
  911.   pTFBGC = (tfbPrivGCPtr)pGC->devPrivates[tfbGCPrivateIndex].ptr;
  912.  
  913.   /* TURN PIP OFF SO WE CAN CHANGE PIP PARAMETERS AND GET A CLEAN PICTURE */
  914.  
  915.   pip_off_with_timeout(ppp->prop, 1);
  916.  
  917.   /* IF THE DRAWABLE DEPTH IS 8 WE KNOW IT MUST BE A StaticGray WINDOW */
  918.  
  919.   if (pDraw->depth == 8)
  920.     {
  921.       if (!ppp->gray)
  922.     {
  923.       pip_source_type(ppp->prop, ppp->pEncoding->id | PIP_GRAY);
  924.       ppp->gray = TRUE;
  925.     }
  926.  
  927.       /* GET COMPOSITE CLIP LIST */
  928.  
  929.       pCFBGC = (cfbPrivGCPtr)pGC->devPrivates[cfbGCPrivateIndex].ptr; 
  930.       pClip = pCFBGC->pCompositeClip;
  931.  
  932.     }
  933.   else
  934.     {
  935.       if (ppp->gray)
  936.     {
  937.       pip_source_type(ppp->prop, ppp->pEncoding->id);
  938.       ppp->gray = FALSE;
  939.     }
  940.  
  941.       /* GET COMPOSITE CLIP LIST */
  942.  
  943.       pTFBGC = (tfbPrivGCPtr)pGC->devPrivates[tfbGCPrivateIndex].ptr; 
  944.       pClip = pTFBGC->pCompositeClip;
  945.     } 
  946.  
  947.   /* IF VIDEO IS CURRENTLY PLAYING INTO DIFFERENT DRAWABLE
  948.      TURN IT OFF; IF DRAWABLE/GC HAVE CHANGED THEN VALIDATE THE
  949.      VIDEO ENABLE */
  950.  
  951.   if ((pGC != ppp->pGC) || (pDraw->serialNumber != ppp->serialNumber))
  952.     {
  953.  
  954.       if (pPort->pDraw)
  955.     {
  956.       /* CLEAR THE OLD VIDEO ENABLED REGION */
  957.  
  958.       fill_video_enable(ppp->prop, 
  959.                 ppp->enabled_box.x1, 
  960.                 ppp->enabled_box.y1, 
  961.                 ppp->enabled_box.x2 - ppp->enabled_box.x1,
  962.                 ppp->enabled_box.y2 - ppp->enabled_box.y1, 00);
  963.  
  964.       ppp->serialNumber = pDraw->serialNumber;
  965.     }
  966.  
  967.       for (nBox=0, pBox=REGION_RECTS(pClip);
  968.        nBox<(int)REGION_NUM_RECTS(pClip); 
  969.        nBox++, pBox++)
  970.     {
  971.       
  972.       x1 = pBox->x1;
  973.       y1 = pBox->y1;
  974.       x2 = pBox->x2;
  975.       y2 = pBox->y2;
  976.       
  977.       fill_video_enable(ppp->prop, x1, y1, x2 - x1, y2 - y1, 0xff);
  978.       
  979.     }
  980.  
  981.       /* SAVE THE BOUNDING BOX OF THE ENABLED VIDEO REGION; IF WE ARE 
  982.      DRAWING INTO THE SAME DRAWABLE */
  983.  
  984.       if (pDraw == pPort->pDraw)
  985.     ppp->enabled_box = pClip->extents;
  986.  
  987.     }
  988.  
  989.   vis = ((WindowPtr)pDraw)->visibility;
  990.  
  991.   if (vis == VisibilityUnobscured) pip_priority(ppp->prop, 0);
  992.   else pip_priority(ppp->prop, 256);
  993.  
  994.   /* SET THE POSITION OF THE VIDEO */
  995.  
  996.   pip_src_area(ppp->prop, vid_x, vid_y, vid_w, vid_h);
  997.  
  998.   pip_dst_area(ppp->prop, pDraw->x+drw_x, pDraw->y+drw_y, drw_w, drw_h);
  999.  
  1000.   if (!pip_on_with_timeout(ppp->prop, 1))
  1001.     {
  1002.       XvdiSendVideoNotify(pPort, pDraw, XvHardError);
  1003.     }
  1004.  
  1005.   /* WAIT FOR THE ONE SHOT TO COMPLETE */
  1006.  
  1007.   pip_off_with_timeout(ppp->prop, 1);
  1008.  
  1009.   /* CLEAR THE ENABLE PLANE IF WE ARE GOING BACK TO ANOTHER DRAWABLE */
  1010.  
  1011.   if (pDraw != pPort->pDraw)
  1012.     {
  1013.       pBox = &((WindowPtr)pDraw)->winSize.extents;
  1014.       fill_video_enable(ppp->prop, pBox->x1, pBox->y1, 
  1015.             pBox->x2-pBox->x1, pBox->y2-pBox->y1, 00);
  1016.     }
  1017.  
  1018.   if (pGC != ppp->pGC)
  1019.     {
  1020.       ppp->serialNumber = NEXT_SERIAL_NUMBER;
  1021.     }
  1022.  
  1023.   /* RESTART VIDEO SINCE WE STOPPED IT */
  1024.  
  1025.   if (pPort->pDraw)
  1026.     {
  1027.  
  1028.       /* IF THE GC HAS BEEN DESTROYED THEN JUST PREEMPT THE VIDEO */
  1029.  
  1030.       if (!ppp->pGC)
  1031.     {
  1032.       XvdiSendVideoNotify(pPort, pDraw, XvPreempted);
  1033.       return Success;
  1034.     }
  1035.  
  1036.       if (ppp->pGC->serialNumber != pPort->pDraw->serialNumber)
  1037.     ValidateGC(pPort->pDraw, ppp->pGC);
  1038.  
  1039.       XvropPutVideo((ClientPtr)NULL, pPort->pDraw, pPort, ppp->pGC, 
  1040.             ppp->vx, ppp->vy, ppp->vw, ppp->vh,
  1041.             ppp->dx, ppp->dy, ppp->dw, ppp->dh);
  1042.  
  1043.     }
  1044.  
  1045.   return Success;
  1046.  
  1047. }
  1048.  
  1049. static int
  1050. XvropGetVideo(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  1051.           drw_x, drw_y, drw_w, drw_h)
  1052. ClientPtr client;
  1053. DrawablePtr pDraw;
  1054. XvPortPtr pPort;
  1055. GCPtr pGC;
  1056. INT16 vid_x, vid_y, drw_x, drw_y;
  1057. CARD16 vid_w, vid_h, drw_w, drw_h;
  1058.  
  1059. {
  1060.   return BadMatch;
  1061. }
  1062.  
  1063. static int
  1064. XvropGetStill(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  1065.           drw_x, drw_y, drw_w, drw_h)
  1066. ClientPtr client;
  1067. DrawablePtr pDraw;
  1068. XvPortPtr pPort;
  1069. GCPtr pGC;
  1070. INT16 vid_x, vid_y, drw_x, drw_y;
  1071. CARD16 vid_w, vid_h, drw_w, drw_h;
  1072.  
  1073. {
  1074.   return BadMatch;
  1075. }
  1076.  
  1077.  
  1078. static int
  1079. XvropStopVideo(client, pPort, pDraw)
  1080. ClientPtr client;
  1081. XvPortPtr pPort;
  1082. DrawablePtr pDraw;
  1083.  
  1084. {
  1085.   XvropPortPtr ppp;
  1086.   GCPtr pGCTemp;
  1087.  
  1088.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  1089.  
  1090.   /* CLEAR THE VIDEO ENABLE PLANE */
  1091.  
  1092.   pip_off_with_timeout(ppp->prop, 1);
  1093.  
  1094.   /* CLEAR THE VIDEO ENABLE PLANE */
  1095.  
  1096.   fill_video_enable(ppp->prop, 
  1097.             ppp->enabled_box.x1, 
  1098.             ppp->enabled_box.y1, 
  1099.             ppp->enabled_box.x2 - ppp->enabled_box.x1,
  1100.             ppp->enabled_box.y2 - ppp->enabled_box.y1, 00);
  1101.  
  1102.   /* UNWRAP GC DESTROY PROCEDURE IF NECESSARY */
  1103.  
  1104.   if (ppp->pGC)
  1105.     {
  1106.       pGCTemp = ppp->pGC;
  1107.       ppp->pGC = (GCPtr)NULL;
  1108.       ChangeGC(pGCTemp, 0, 0); /* USE CHANGE GC TO UNWRAP GC */
  1109.     }
  1110.  
  1111.   return Success;
  1112. }
  1113.  
  1114.  
  1115. static int
  1116. XvropSetPortAttribute(client, pPort, attribute, value)
  1117. ClientPtr client;
  1118. XvPortPtr pPort;
  1119. Atom attribute;
  1120. INT32 value;
  1121.  
  1122. {
  1123.   int ii;
  1124.   unsigned char lut[256];
  1125.   XvAdaptorPtr pa;
  1126.   XvEncodingPtr pe;
  1127.   XvropPortPtr ppp;
  1128.   float contrast, brightness;
  1129.   int on_off;
  1130.   int rop_value;
  1131.  
  1132.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  1133.  
  1134.   on_off = pip_off(ppp->prop,1);
  1135.  
  1136.   /* FIND THE ATTRIBUTE AND SET IT; XXX --- MORE LATER */
  1137.  
  1138.   if (attribute == XvropEncoding)
  1139.     {
  1140.       pa = pPort->pAdaptor;
  1141.       pe = pa->pEncodings;
  1142.       for (ii=0; ii<pa->nEncodings; ii++)
  1143.     {
  1144.       if (pe->id == (XvEncodingID)value)
  1145.         {
  1146.  
  1147.           /* SAVE NEW ENCODING ID */
  1148.  
  1149.           ppp->pEncoding = pe;
  1150.  
  1151.           if (ppp->gray)
  1152.         pip_source_type(ppp->prop, pe->id | PIP_GRAY);
  1153.           else
  1154.         pip_source_type(ppp->prop, pe->id);
  1155.  
  1156.           break;
  1157.         }
  1158.       pe++;
  1159.     }
  1160.       if (ii>=pa->nEncodings) return _XvBadEncoding;
  1161.     }
  1162.   else if (attribute == XvropHue)
  1163.     {
  1164.  
  1165.       if (value < -1000) value = -1000;
  1166.       if (value > 1000) value = 1000;
  1167.  
  1168.       /* HUE IS THE LOCATION AROUND THE COLOR CIRCLE */
  1169.       /* MAP 0..1000 INTO 0..127 AND -1..-1000 INTO 255..128 */
  1170.  
  1171.       if (value >= 0) rop_value = (127*value)/1000;
  1172.       else rop_value = (127*(1000+value))/999 + 128;
  1173.  
  1174.       pip_hue(ppp->prop,rop_value); 
  1175.       ppp->hue = value;
  1176.     }
  1177.   else if (attribute == XvropSaturation)
  1178.     {
  1179.       if (value < -1000) value = -1000;
  1180.       if (value > 1000) value = 1000;
  1181.  
  1182.       /* MAP -1000..1000 into 0..255 */
  1183.  
  1184.       pip_saturation(ppp->prop,(255*(value+1000))/2000); 
  1185.       ppp->saturation = value;
  1186.     }
  1187.   else if (attribute == XvropBrightness)
  1188.     {
  1189.       if (value < -1000) value = -1000;
  1190.       if (value > 1000) value = 1000;
  1191.       contrast = ppp->contrast;
  1192.       brightness = value;
  1193.       GetAdjustLUT(lut,contrast,brightness,0.0,FALSE,FALSE);
  1194.       pip_load_dcsc(ppp->prop,lut);
  1195.       ppp->brightness = value;
  1196.     }
  1197.   else if (attribute == XvropContrast)
  1198.     {
  1199.       if (value < -1000) value = -1000;
  1200.       if (value > 1000) value = 1000;
  1201.       contrast = value + 120.0; /* ADJUST FOR RASTEROPS VIDEO PIXEL RANGE */
  1202.       brightness = ppp->brightness;
  1203.       GetAdjustLUT(lut,contrast,brightness,0.0,FALSE,FALSE);
  1204.       pip_load_dcsc(ppp->prop,lut);
  1205.       ppp->contrast = value;
  1206.     }
  1207.   else
  1208.       return BadMatch;
  1209.  
  1210.   if (on_off) pip_on(ppp->prop);
  1211.  
  1212.   XvdiSendPortNotify(pPort, attribute, value);
  1213.  
  1214.   return Success;
  1215. }
  1216.  
  1217. static int
  1218. XvropGetPortAttribute(client, pPort, attribute, p_value)
  1219. ClientPtr client;
  1220. XvPortPtr pPort;
  1221. Atom attribute;
  1222. INT32 *p_value;
  1223.  
  1224. {
  1225.  
  1226.   XvropPortPtr ppp;
  1227.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  1228.  
  1229.   /* FIND THE ATTRIBUTE AND RETURN ITS VALUE; XXX --- MORE LATER */
  1230.  
  1231.   if (attribute == XvropEncoding)
  1232.     {
  1233.       *p_value = ppp->pEncoding->id;
  1234.     }
  1235.   else if (attribute == XvropHue)
  1236.     {
  1237.       *p_value = ppp->hue;
  1238.     }
  1239.   else if (attribute == XvropSaturation)
  1240.     {
  1241.       *p_value = ppp->saturation;
  1242.     }
  1243.   else if (attribute == XvropBrightness)
  1244.     {
  1245.       *p_value = ppp->brightness;
  1246.     }
  1247.   else if (attribute == XvropContrast)
  1248.     {
  1249.       *p_value = ppp->contrast;
  1250.     }
  1251.   else 
  1252.       return BadMatch;
  1253.  
  1254.   return Success;
  1255.  
  1256. }
  1257.  
  1258. static int
  1259. XvropQueryBestSize(client, pPort, motion, vid_w, vid_h, drw_w, drw_h, p_w, p_h)
  1260. ClientPtr client;
  1261. XvPortPtr pPort;
  1262. CARD8 motion;
  1263. CARD16 vid_w,vid_h;
  1264. CARD16 drw_w,drw_h;
  1265. unsigned int *p_w, *p_h;
  1266.  
  1267. {
  1268.   XvropPortPtr ppp;
  1269.   XvEncodingPtr pe;
  1270.   int vid_x,vid_y,drw_x,drw_y;
  1271.   extern WindowPtr *WindowTable;
  1272.  
  1273.   vid_x = vid_y = drw_x = drw_y = 0;
  1274.  
  1275.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  1276.   pe = ppp->pEncoding;
  1277.  
  1278.   /* USE THE SAME GEOMETRY CONSTRAINT PROC THAT WE USE FOR GET AND PUT */
  1279.  
  1280.   XvropConstrainVideo(WindowTable[pPort->pAdaptor->pScreen->myNum], pe, 
  1281.               vid_x, vid_y, vid_w, vid_h,
  1282.               drw_x, drw_y, drw_w, drw_h,
  1283.               &vid_x, &vid_y, &vid_w, &vid_h,
  1284.               &drw_x, &drw_y, p_w, p_h);
  1285.  
  1286.   return Success;
  1287.  
  1288. }
  1289.  
  1290. static void
  1291. XvropDestroyGC(pGC)
  1292.  
  1293. GCPtr pGC;
  1294.  
  1295. {
  1296.  
  1297.   Bool status;
  1298.   ScreenPtr pScreen;
  1299.   XvScreenPtr pxvs;
  1300.   XvropScreenPtr props;
  1301.   XvropPortPtr ppp;
  1302.   
  1303.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1304.  
  1305.   /* JUST CHECKING */
  1306.  
  1307.   if (ppp->pGC == pGC)
  1308.     {
  1309.       ppp->pGC = (GCPtr)NULL;
  1310.     }
  1311.  
  1312.   pGC->funcs = ppp->wrapFuncs;
  1313.   (* pGC->funcs->DestroyGC)(pGC);
  1314.  
  1315.   /* DON'T REWRAP THE FUNCS */
  1316.  
  1317. }
  1318.  
  1319. static void
  1320. XvropValidateGC(pGC, changes, pDraw)
  1321.  
  1322. GCPtr pGC;
  1323. Mask changes;
  1324. DrawablePtr pDraw;
  1325.  
  1326. {
  1327.  
  1328.   Bool status;
  1329.   ScreenPtr pScreen;
  1330.   XvScreenPtr pxvs;
  1331.   XvropScreenPtr props;
  1332.   XvropPortPtr ppp;
  1333.  
  1334.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1335.  
  1336.   pGC->funcs = ppp->wrapFuncs;
  1337.  
  1338.   (* pGC->funcs->ValidateGC)(pGC, changes, pDraw);
  1339.  
  1340.   /* IF THIS GC IS BEING USED FOR VIDEO THEN UPDATE THE VIDEO SERIAL NUMBER */
  1341.  
  1342.   if (ppp->pGC == pGC)
  1343.     {
  1344.       ppp->serialNumber = NEXT_SERIAL_NUMBER;
  1345.     }
  1346.  
  1347.   pGC->funcs = &XvropGCFuncs;
  1348.  
  1349. }
  1350.  
  1351. static void
  1352. XvropChangeGC (pGC, mask)
  1353.     GCPtr   pGC;
  1354.     unsigned long   mask;
  1355. {
  1356.   XvropPortPtr ppp;
  1357.  
  1358.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1359.  
  1360.   pGC->funcs = ppp->wrapFuncs;
  1361.  
  1362.   (*pGC->funcs->ChangeGC) (pGC, mask);
  1363.  
  1364.   /* CHECK TO SEE IF GC IS STILL BEING USED FOR VIDEO; IF NOT THEN
  1365.      LEAVE IT UNWRAPPED */
  1366.  
  1367.   if (ppp->pGC == pGC)
  1368.     {
  1369.       pGC->funcs = &XvropGCFuncs;
  1370.     }
  1371.  
  1372. }
  1373.  
  1374. static void
  1375. XvropCopyGC (pGCSrc, mask, pGCDst)
  1376.     GCPtr   pGCSrc, pGCDst;
  1377.     unsigned long   mask;
  1378. {
  1379.   XvropPortPtr ppp;
  1380.  
  1381.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1382.  
  1383.   pGCDst->funcs = ppp->wrapFuncs;
  1384.  
  1385.   (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
  1386.  
  1387.   pGCDst->funcs = &XvropGCFuncs;
  1388. }
  1389.  
  1390. static void
  1391. XvropChangeClip(pGC, type, pvalue, nrects)
  1392.     GCPtr       pGC;
  1393.     int         type;
  1394.     pointer     pvalue;
  1395.     int         nrects;
  1396. {
  1397.   XvropPortPtr ppp;
  1398.  
  1399.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1400.  
  1401.   pGC->funcs = ppp->wrapFuncs;
  1402.  
  1403.   (* pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
  1404.  
  1405.   pGC->funcs = &XvropGCFuncs;
  1406. }
  1407.  
  1408. static void
  1409. XvropCopyClip(pgcDst, pgcSrc)
  1410.     GCPtr pgcDst, pgcSrc;
  1411. {
  1412.   XvropPortPtr ppp;
  1413.  
  1414.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1415.  
  1416.   pgcDst->funcs = ppp->wrapFuncs;
  1417.  
  1418.   (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
  1419.  
  1420.   pgcDst->funcs = &XvropGCFuncs;
  1421. }
  1422.  
  1423. static void
  1424. XvropDestroyClip(pGC)
  1425.     GCPtr       pGC;
  1426. {
  1427.   XvropPortPtr ppp;
  1428.  
  1429.   ppp = (XvropPortPtr)XvropPorts->devPriv.ptr;
  1430.  
  1431.   pGC->funcs = ppp->wrapFuncs;
  1432.  
  1433.   (* pGC->funcs->DestroyClip)(pGC);
  1434.  
  1435.   pGC->funcs = &XvropGCFuncs;
  1436. }
  1437.  
  1438.  
  1439. static void
  1440. XvropClipNotify(pWin, dx, dy)
  1441.  
  1442. WindowPtr pWin;
  1443. int dx,dy;
  1444.  
  1445. {
  1446.  
  1447.   ScreenPtr pScreen;
  1448.   XvScreenPtr pxvs;
  1449.   XvPortPtr pp;
  1450.   XvropScreenPtr props;
  1451.   Bool noExposures;
  1452.  
  1453.   pScreen = pWin->drawable.pScreen;
  1454.  
  1455.   pxvs = (XvScreenPtr)pWin->drawable.pScreen->devPrivates[XvScreenIndex].ptr;
  1456.  
  1457.   /* XXX---NEXT STATEMENT IS ONLY NECESSARY IF WE ARE USING miClipNotify */
  1458.  
  1459.   if (!pxvs) return;
  1460.  
  1461.   props = (XvropScreenPtr)pxvs->devPriv.ptr;
  1462.  
  1463.   pScreen->ClipNotify = props->ClipNotify;
  1464.  
  1465.   /* STOP VIDEO IN WINDOW IF NECESSARY */
  1466.  
  1467.   pp = XvropPorts;
  1468.  
  1469.   if (pp->pDraw == (DrawablePtr)pWin)
  1470.     {
  1471.  
  1472.       XvropHaltVideo(pp);
  1473.  
  1474.     }
  1475.  
  1476.   if (pScreen->ClipNotify) (* pScreen->ClipNotify)(pWin, dx, dy);
  1477.  
  1478.   pScreen->ClipNotify = XvropClipNotify;
  1479.  
  1480. }
  1481.  
  1482. static void
  1483. XvropCopyWindow(pWin, lastposition, pRegionSrc)
  1484. WindowPtr pWin;
  1485. DDXPointRec lastposition;
  1486. RegionPtr pRegionSrc;
  1487.  
  1488. {
  1489.  
  1490.   ScreenPtr pScreen;
  1491.   WindowPtr pChild;
  1492.   XvScreenPtr pxvs;
  1493.   XvPortPtr pp;
  1494.   XvropScreenPtr props;
  1495.  
  1496.   pp = XvropPorts;
  1497.  
  1498.   pScreen = pWin->drawable.pScreen;
  1499.  
  1500.   pxvs = (XvScreenPtr)pWin->drawable.pScreen->devPrivates[XvScreenIndex].ptr;
  1501.   props = (XvropScreenPtr)pxvs->devPriv.ptr;
  1502.  
  1503.   pScreen->CopyWindow = props->CopyWindow;
  1504.  
  1505.   pChild = pWin;
  1506.   while (1)
  1507.     {
  1508.       if (pChild->viewable)
  1509.     {
  1510.       if (pp->pDraw == (DrawablePtr)pChild)
  1511.         XvropHaltVideo(pp);
  1512.  
  1513.       if (pChild->firstChild)
  1514.         {
  1515.           pChild = pChild->firstChild;
  1516.           continue;
  1517.         }
  1518.     }
  1519.       while (!pChild->nextSib && (pChild != pWin))
  1520.     pChild = pChild->parent;
  1521.       if (pChild == pWin)
  1522.     break;
  1523.       pChild = pChild->nextSib;
  1524.     }
  1525.  
  1526.   (* pScreen->CopyWindow)(pWin, lastposition, pRegionSrc);
  1527.  
  1528.   pScreen->CopyWindow = XvropCopyWindow;
  1529.  
  1530. }
  1531.  
  1532. static void
  1533. XvropWindowExposures(pWin, pReg, pOtherReg)
  1534. WindowPtr pWin;
  1535. RegionPtr pReg;
  1536. RegionPtr pOtherReg;
  1537.  
  1538. {
  1539.  
  1540.   ScreenPtr pScreen;
  1541.   XvScreenPtr pxvs;
  1542.   XvropScreenPtr props;
  1543.   XvPortPtr pp;
  1544.   XvropPortPtr ppp;
  1545.   
  1546.   pScreen = pWin->drawable.pScreen;
  1547.  
  1548.   pxvs = (XvScreenPtr)pWin->drawable.pScreen->devPrivates[XvScreenIndex].ptr;
  1549.   props = (XvropScreenPtr)pxvs->devPriv.ptr;
  1550.  
  1551.   pScreen->WindowExposures = props->WindowExposures;
  1552.  
  1553.   pp = XvropPorts;
  1554.  
  1555.   if ((pp->pDraw) && (((WindowPtr)pp->pDraw)->realized))
  1556.     {
  1557.       ppp = (XvropPortPtr)pp->devPriv.ptr;
  1558.       if (pp->pDraw->serialNumber != ppp->serialNumber)
  1559.     XvropRestartVideo(pp);
  1560.     }
  1561.  
  1562.   (* pScreen->WindowExposures)(pWin, pReg, pOtherReg);
  1563.  
  1564.   pScreen->WindowExposures = XvropWindowExposures;
  1565.  
  1566. }
  1567.  
  1568. static Bool
  1569. XvropUnrealizeWindow(pWin)
  1570. WindowPtr pWin;
  1571.  
  1572. {
  1573.  
  1574.   ScreenPtr pScreen;
  1575.   XvScreenPtr pxvs;
  1576.   XvropScreenPtr props;
  1577.   XvPortPtr pp;
  1578.   int status;
  1579.  
  1580.   pScreen = pWin->drawable.pScreen;
  1581.  
  1582.   pxvs = (XvScreenPtr)pWin->drawable.pScreen->devPrivates[XvScreenIndex].ptr;
  1583.   props = (XvropScreenPtr)pxvs->devPriv.ptr;
  1584.  
  1585.   pScreen->UnrealizeWindow = props->UnrealizeWindow;
  1586.  
  1587.   pp = XvropPorts;
  1588.  
  1589.   if (pp->pDraw == (DrawablePtr)pWin)
  1590.     {
  1591.       XvropHaltVideo(pp);
  1592.     }
  1593.  
  1594.   status = (* pScreen->UnrealizeWindow)(pWin);
  1595.  
  1596.   pScreen->UnrealizeWindow = XvropUnrealizeWindow;
  1597.  
  1598.   return status;
  1599.  
  1600. }
  1601.  
  1602. XvropHaltVideo(pPort)
  1603.  
  1604. XvPortPtr pPort;
  1605.  
  1606. {
  1607.  
  1608.   XvropPortPtr ppp;
  1609.   
  1610.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  1611.  
  1612.   pip_off_with_timeout(ppp->prop, 1);
  1613.   
  1614.   /* CLEAR THE VIDEO ENABLE PLANE */
  1615.  
  1616.   fill_video_enable(ppp->prop, 
  1617.             ppp->enabled_box.x1, 
  1618.             ppp->enabled_box.y1, 
  1619.             ppp->enabled_box.x2 - ppp->enabled_box.x1,
  1620.             ppp->enabled_box.y2 - ppp->enabled_box.y1, 00);
  1621.  
  1622. }
  1623.  
  1624. XvropRestartVideo(pPort)
  1625.  
  1626. XvPortPtr pPort;
  1627.  
  1628. {
  1629.   XvropPortPtr ppp;
  1630.   
  1631.   ppp = (XvropPortPtr)pPort->devPriv.ptr;
  1632.  
  1633.   if (ppp->pGC)
  1634.     {
  1635.  
  1636.       if (ppp->pGC->serialNumber != pPort->pDraw->serialNumber)
  1637.     ValidateGC(pPort->pDraw, ppp->pGC);
  1638.  
  1639.       XvropPutVideo((ClientPtr)NULL, 
  1640.             pPort->pDraw, pPort, ppp->pGC, 
  1641.             ppp->vx, ppp->vy, ppp->vw, ppp->vh,
  1642.             ppp->dx, ppp->dy, ppp->dw, ppp->dh);
  1643.     }
  1644.   else
  1645.     {
  1646.       XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
  1647.     }
  1648.  
  1649. }
  1650.  
  1651.  
  1652. /*
  1653. ** CARVER --- 04.06.91
  1654. **
  1655. **   I wanted to note that the following code, given to us by Robert
  1656. **   Ulichney, is used to control RasterOps contrast and brightness only.
  1657. **   Hue and saturation are not table driven in the RasterOps.
  1658. **
  1659. */
  1660.  
  1661.  
  1662. /*
  1663. **++
  1664. **  FACILITY:
  1665. **
  1666. **    GetAdjustLUT, 
  1667. **    A fast routine to generate a general color component adjust LUT.
  1668. **
  1669. **  ABSTRACT:
  1670. **
  1671. **    This routine very quickly and efficiently generates a look-up
  1672. **    table of 256 input values to 256 output values to be used for
  1673. **    adjusting a color component of pixels in an image. It can be
  1674. **    used to adjust chromanance, as well as luminance values.
  1675. **
  1676. **    It is convenient to picture the mapping as a curve on a graph
  1677. **    where input values are along the "x" axis, and output values are
  1678. **    along the "y" axis. The identity or "no-change" function would
  1679. **    be a line of unity slope passing through the origin.
  1680. **
  1681. **    The arguments of the routine are described in detail in the code
  1682. **    comments. Inputs are contrast ("slope" in the case of luminace,
  1683. **    "saturation" or "chroma" in the case of chrominance), brightness
  1684. **    (y-offset), an x-offset to be used on chrominace components for
  1685. **    the purpose of changing the white point in combination with the
  1686. **    y-offset, and controls for negating the input and/or the output.
  1687. **
  1688. **
  1689. **
  1690. **
  1691. **  AUTHOR:
  1692. **
  1693. **    Robert Ulichney
  1694. **        Internet: ulichney@gauss.enet.dec.com
  1695. **        Phone:      503-493-2503
  1696. **
  1697. **  CREATION DATE:    15-May-1991
  1698. **
  1699. **  MODIFICATION HISTORY:
  1700. **
  1701. **--
  1702. */
  1703.  
  1704.  
  1705.  
  1706. /*
  1707. **  INCLUDE FILES: (none)
  1708. */
  1709.  
  1710. /* 
  1711. **  MACRO DEFINITIONS: (none)
  1712. */
  1713.  
  1714. /*
  1715. **  OTHER DEFINITIONS: 
  1716. */
  1717.  
  1718. typedef int    boolean;    /* 0=false, 1=true */
  1719.  
  1720. /*    GetAdjustLUT    */
  1721.  
  1722. GetAdjustLUT(AdjustLUT,contrast,brightness,Xoffset,negIn,negOut)
  1723. unsigned char    AdjustLUT[256];
  1724. float        contrast;    /* "Slope" of the transfer function.
  1725.                 ** 0 => no change, +1000 => vertical slope, 
  1726.                 ** -1000 => zero slope (flat).  While the 
  1727.                 ** the variable name is clear for use as a 
  1728.                 ** luminance adjustment, it takes on the 
  1729.                 ** meaning of "saturation" of "chroma" control
  1730.                 ** when used as an adjustment to a chrominance
  1731.                 ** value. The maximum allowable contrast
  1732.                 ** magnitude is 1000. 
  1733.                 */
  1734. float        brightness;    /* "Y" offset of the transfer function.
  1735.                 ** 0 => no change, +100 => increase all inputs 
  1736.                 ** by half the range, -100 => decreass all 
  1737.                 ** inputs by half the range. This can also
  1738.                 ** be used for chrominance adjustment in 
  1739.                 ** combination with Xoffset to change the 
  1740.                 ** white point. 
  1741.                 ** The maximum allowable brightness magnitude 
  1742.                 ** is 1000. Because most all adjustments will
  1743.                 ** involve magnitudes between 0 and 100, 
  1744.                 ** user interfaces, such as sliders, should
  1745.                 ** give as much vernier in this range as
  1746.                 ** for magnitudes between 100 and 1000. 
  1747.                 ** When this parameter is used to adjust white
  1748.                 ** point, the user interface should only provide
  1749.                 ** means to input magnitudes between 0 and 100.
  1750.                 */
  1751. float        Xoffset;    /* The same as brightness, but effecting a
  1752.                 ** translation of the transfer function in the 
  1753.                 ** "X" direction.  This is intended for use
  1754.                 ** with chrominance adjustment in combination
  1755.                 ** with brightness to change the white point. 
  1756.                 */
  1757. boolean        negIn;        /* A flag to indicate whether the input data is
  1758.                 ** to be negated BEFORE adjustment occurs. 
  1759.                 ** This would be necessary if the input data
  1760.                 ** intends 0 to represent white. 
  1761.                 */
  1762. boolean        negOut;        /* A flag to indicate whether the output data 
  1763.                 ** to be negated AFTER adjustment occurs.  This 
  1764.                 ** would be needed when the output device 
  1765.                 ** interprets 0 as white. 
  1766.                 */
  1767.                 /* NOTE: If negation is to occur, it is 
  1768.                 ** important to correctly choose negIn or 
  1769.                 ** negOut, as they are not interchangeable.
  1770.                 ** A wronge choice will lead to adjustments
  1771.                 ** producing unexpected results. */
  1772. {    
  1773.     float        m;    /* slope */
  1774.     float        b;    /* y-intercept */
  1775.     int        x;    /* input value to AdjustLUT */
  1776.     float        y;    /* pre-truncated value y=m*x+b */
  1777.     int        maxV;    /* upper-bound for table-loading loop */
  1778.     int        lo;    /* x value at cross of y=m*x+b with y=0 */
  1779.     int        hi;    /* x value at cross of y=m*x+b with y=255 */
  1780.  
  1781. /* The strategy is to first form the equation of a line, y=m*x+b, and 
  1782. ** establish the appropriate m and b. */
  1783.  
  1784. /* Range checks */
  1785.     /* Check for the special case of a vertical slope */
  1786.     if(contrast>999) contrast = 999; 
  1787.         /* slope = 1000 is effectively infinite */
  1788.     
  1789.     /* Correct for under-range contrast values */
  1790.     if(contrast<(-1000)) contrast = (-1000);  /* zero slope */
  1791.  
  1792. /* Find the slope, m */
  1793.     if(contrast>0)  m = 1000 / (1000-contrast);
  1794.     else        m = (1000+contrast)/1000;
  1795.  
  1796. /* Find the y-intercept */
  1797. /* The y-intercept, b, is influenced by three factors.
  1798. ** First, contrast effectively rotates the line about a pivot at (127.5,127.5).
  1799. ** In general, a line pivited at point (a,a) with slope m, has a y-intercept
  1800. ** b=a*(1-m).  So, we start with b=127.5*(1-m).
  1801. ** 
  1802. ** Secondly, the effect of brightness adds (127.5/100)*brightness to b.
  1803. ** The effect of brightness on a line y=m*x+b is:
  1804. **         y = m*x + (b + (127.5/100)*brightness)
  1805. ** 
  1806. ** Thirdly, the effect of Xoffset on a line y=m*x+b is:
  1807. **         y = m*(x-(127.5/100)*Xoffset) + b
  1808. **          = m*x + (b - m*(127.5/100)*Xoffset)
  1809. ** 
  1810. ** Together, these three factors yield a y-intercept 
  1811. **    b = 127.5*(1-m) + (127.5/100)*brightness - m*(127.5/100)*Xoffset
  1812. ** or, more simply:
  1813. */
  1814.     b = (1.275)*(100 + brightness - m*(100+Xoffset));
  1815.  
  1816. /* Check if input data is to be negated.  If so, reflect the function about 
  1817. ** the line x=127.5.  
  1818. ** Note: In general, reflecting y=mx+b about the line x=a results in the line
  1819. ** y=(-m)*x + (2*a*m+b).
  1820. */
  1821.     if(negIn) {
  1822.         b = 255*m + b;
  1823.         m = (-m);
  1824.     }
  1825.  
  1826. /* Check if output data is to be negated.  If so, reflect the function about
  1827. ** the line y=127.5.
  1828. ** Note: In general, reflecting y=mx+b about the line y=c results in the line 
  1829. ** y=(-m)*x + (2*c-b).
  1830. */
  1831.     if(negOut) {
  1832.         b = 255 - b;
  1833.         m = (-m);
  1834.     }
  1835.  
  1836. /* Find the value of x at the intersection of the function y=mx+b with the
  1837. ** lines at y=0 and y=255. These values of "lo" and "hi" will be used to more
  1838. ** quickly generate the AdjustLUT with out needing to check for out-of-bounds
  1839. ** at each value. */
  1840.     if(m != 0) {
  1841.         hi = (255-b)/m;        /* intersection with y=255 */
  1842.         lo = (-b/m);        /* intersection with y=0 */
  1843.     /* Note that both of these values are truncated to the integer x value 
  1844.     ** just below the point of intersection.
  1845.     */
  1846.     }
  1847.     else hi=1000, lo=(-1000);    /* For the case of zero slope,
  1848.                     ** force outside the range of (0,256).
  1849.                     */
  1850.  
  1851. /******************** Now load the table (finally!) *********************/
  1852. /* Treat the cases of positive and negative slope separately. */
  1853.  
  1854. /* Non-negative slope case */
  1855.     if(m>=0) {    
  1856.         if(lo>255) lo=255;    /* The entire table is clipped to 0. */
  1857.  
  1858.         /* Fill the LUT in order, from x=0 through x=255 */
  1859.         for(x=0; x<=lo; x++) AdjustLUT[x]=0;     /* clip low values */
  1860.  
  1861.         maxV = (hi>255)? 255:hi; /* Fill the table with values of 
  1862.                     ** y=m*x+b only up to the point where
  1863.                     ** the function crosses the line y=255,
  1864.                     ** or, if it never reaches y=255, stop
  1865.                     ** at x=255. */
  1866.         for(y=m*x+b+.5; x<=maxV; x++,y+=m) AdjustLUT[x]=y;
  1867.         
  1868.         while(x<=255) AdjustLUT[x++]=255;    /* clip high values */
  1869.     }
  1870.  
  1871. /* Negative slope case */
  1872.     else {
  1873.         if(hi>255) hi=255;    /* The entire table is clipped to 255.*/
  1874.  
  1875.         /* Fill the LUT in order, from x=0 through x=255 */
  1876.         for(x=0; x<=hi; x++) AdjustLUT[x]=255;     /* clip high values */
  1877.  
  1878.         maxV = (lo>255)? 255:lo; /* Fill the table with values of 
  1879.                     ** y=m*x+b only up to the point where
  1880.                     ** the function crosses the line y=0,
  1881.                     ** or, if it never reaches y=0, stop
  1882.                     ** at x=255. */
  1883.         for(y=m*x+b+.5; x<=maxV; x++,y+=m) AdjustLUT[x]=y;
  1884.         
  1885.         while(x<=255) AdjustLUT[x++]=0;    /* clip low values */
  1886.     }
  1887.         
  1888. }  /* End of GetAdjustLUT */
  1889.